//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <aura.h>
#include "wince.h"
#include "private.h"

AURA_API AuraModule_Load(
        /* [in] */ Aura_PWChar name,
        /* [in] */ Aura_ModuleLoadFlags flags,
        /* [out] */ Aura_Handle * phModule)
{
    HINSTANCE hModule = NULL;

    assert(NULL != name);
    assert(L'\0' != (wchar_t)name[0]);
    assert(NULL != phModule);

    hModule = LoadLibraryW((LPCWSTR)name);
    if (NULL == hModule) {
        goto E_FAIL_EXIT;
    }

    *phModule = hModule;
    return AURA_NOERROR;

E_FAIL_EXIT:
#if defined(_DEBUG)
    if (ERROR_MOD_NOT_FOUND == GetLastError()
        || ERROR_FILE_NOT_FOUND == GetLastError()) {
        Aura_printf("%S not found!!!\n", name);
    }
#endif
    return GetLastAuraECode();
}

AURA_API AuraModule_Unload(
        /* [in] */ Aura_Handle hModule)
{
    BOOL bSuccess = FALSE;

    bSuccess = FreeLibrary(hModule);
    if (!bSuccess) {
        goto E_FAIL_EXIT;
    }

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraModule_GetInformation(
        /* [in] */ Aura_Handle hModule,
        /* [out] */ Aura_Address * pBaseAddr,
        /* [out] */ Aura_Address * pEntryAddr,
        /* [out] */ Aura_MemorySize * pSizeOfImage)
{
    MODULEINFO moduleInfo;
    Aura_Bool bSuccess = FALSE;
    Aura_ECode ec = AURA_NOERROR;

    assert(NULL != hModule);
    assert(NULL != pBaseAddr);
    assert(NULL != pEntryAddr);
    assert(NULL != pSizeOfImage);

    memset((void *)&moduleInfo, 0, sizeof(moduleInfo));
    bSuccess = GetModuleInformation(
                            GetCurrentProcess(),
                            hModule,
                            &moduleInfo,
                            sizeof(moduleInfo));
    if (!bSuccess) {
        goto E_FAIL_EXIT;
    }

    *pBaseAddr    = (Aura_Address)moduleInfo.lpBaseOfDll;
    *pEntryAddr   = (Aura_Address)moduleInfo.EntryPoint;
    *pSizeOfImage = (Aura_MemorySize)moduleInfo.SizeOfImage;

    return ec;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraModule_GetFileName(
        /* [in] */ Aura_Handle hModule,
        /* [out] */ Aura_PWChar pwFileName,
        /* [out] */ Aura_PWChar pwPathName)
{
#define __MAX_PATH__ 260
    DWORD   length = 0;
    wchar_t fileName[__MAX_PATH__];
    wchar_t * pLastSlash = NULL;
    wchar_t * pFileName = (wchar_t *)pwFileName;
    wchar_t * pPathName = (wchar_t *)pwPathName;

    assert(NULL != hModule);
    assert(NULL != pFileName);
    assert(NULL != pPathName);

    length = GetModuleFileNameW(hModule, fileName, __MAX_PATH__);
    if (!length) {
        goto E_FAIL_EXIT;
    }
    pLastSlash = wcsrchr(fileName, L'\\');
    wcscpy((wchar_t *)pFileName, pLastSlash + 1);

    pPathName[0] = L'C';
    pPathName[1] = L':';    //It's short, so I don't think it's necessary to using wcscpy()
    wcscpy((wchar_t *)pPathName + 2, fileName);

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraModule_GetProcAddressByName(
        /* [in] */ Aura_Handle hModule,
        /* [in] */ Aura_PChar name,
        /* [out] */ Aura_Address * pProcAddress)
{
    FARPROC procAddr = NULL;

    assert(NULL != hModule);
    assert(NULL != name);
    assert('\0' != (char)name[0]);
    assert(NULL != pProcAddress);

    procAddr = GetProcAddressA((HINSTANCE)hModule,
                         (LPCSTR)(const char*)name);
    if (NULL == procAddr) {
        goto E_FAIL_EXIT;
    }
    *pProcAddress = (Aura_Address)procAddr;

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraModule_GetProcAddressByOrdinal(
        /* [in] */ Aura_Handle hModule,
        /* [in] */ Aura_Int32 ordinal,
        /* [out] */ Aura_Address * pProcAddress)
{
    FARPROC procAddr = NULL;

    assert(NULL != hModule);
    assert(ordinal > 0);
    assert(NULL != pProcAddress);

    procAddr = GetProcAddressA(hModule, (LPCSTR)ordinal);
    if (NULL == procAddr) {
        goto E_FAIL_EXIT;
    }
    *pProcAddress = (Aura_Address)procAddr;

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraModule_GetResource(
    /* [in] */ Aura_Handle hModule,
    /* [in] */ Aura_PWChar resName,
    /* [in] */ Aura_PWChar resType,
    /* [out] */ Aura_Address * pAddress,
    /* [out] */ Aura_MemorySize * pSize)
{
    HRSRC   hResInfo = NULL;
    HGLOBAL hResData = NULL;
    LPVOID  pResData = NULL;

    assert(NULL != resName);
    assert(L'\0' != (wchar_t)resName[0]);
    assert(NULL != resType);
    assert(L'\0' != (wchar_t)resType[0]);
    assert(NULL != pAddress);
    assert(NULL != pSize);

    // HACK CODE.
    {
        typedef struct
        {
            DWORD don_t_touch0;
            DWORD res_size;
            DWORD don_t_touch1;
            DWORD don_t_touch2;
        }
        res_t;

        hResInfo = FindResourceW((HMODULE)hModule,
                                (LPCWSTR)(const wchar_t *)resName,
                                (LPCWSTR)(const wchar_t *)resType);
        res_t *res = (res_t *)hResInfo;

        *pSize = (Aura_MemorySize)res->res_size;
    }

    hResData = LoadResource((HMODULE)hModule, hResInfo);
    if (NULL == hResData) {
        goto E_FAIL_EXIT;
    }
    pResData = LockResource(hResData);
    if (NULL == pResData) {
        goto E_FAIL_EXIT;
    }
    *pAddress = (Aura_Address)pResData;

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}


